if SERVER then

	StatsDebug = 0
	statssaveinterval = 600 --lower values are BAD.
	AddCSLuaFile("autorun/client/client.lua")
	util.PrecacheSound("sound/achievement_earned.mp3")
	resource.AddFile("sound/achievement_earned.mp3")
	--[[TODO
	
	Removed the revision thing, was stupid, best used for actual release versions/canadates
	Add "Last join date/time" --done
	Add Help Function --done
	Add "High scores" --done, gave me a headache D:
	Make the sound send to the client -fixed
	fix lem's gui from showing "-1d 23, 59" --fixed, also changed to update in real time =D
	Fix Client timer not showing --fixed
	compress size of script a bit using the [  ] *2 thing
	
	Add "Total stats tracked"
	FUTURE Develop plugin system
	Add distance traveled
	Add air time -as in, player total time in the air, total and most at once.
	Add statistics GUI instead of using chat -- I may be able to do this..
	Add statistics compaison table GUI --I'll need lemming or someone else who is derma savvy to fix this up for me..
	Incorperate with modified sui scoreboard with timer that is inside of it
	Further modify that scoreboard to have a  "Show Stats comparason table" button in it
	More detailed stats, Who killed who, with what, how much damage, where, when (maybe not where and when)
	Add a cleanup function
	FUTURE Possible heatmap thing, most likely will never happen.
	More timer skins!
	
	]]--
	
	--[[Stats to track/Table of all tracked stats]]--
	StatsTable = [[
	name
	time
	kills
	deaths
	suicides
	tpropcount
	lastjoined
	achievements
	]]
	
	
	--[[Startup..]]--
	function StartStatsScript()
		CheckStatsDir()
		Msg("Loading Stats Script\n")
		if StatsDebug == 1 then
			DebugPrint("Debug mode activated")
		end
		timer.Create("saveintervaltimer", statssaveinterval, 0, SaveAllData)
		ReadAllData(1)
		TTimeHolder, TTime = GetBiggest("time")
		TKillsHolder, TKills = GetBiggest("kills")
		TDeathsHolder, TDeaths = GetBiggest("deaths")
		TSuicidesHolder, TSuicides = GetBiggest("suicides")
		TPropsHolder, TProps = GetBiggest("tpropcount")
	end
	hook.Add( "Initialize", "startstatsscript", StartStatsScript )

	--[[Debugger for when we run into problems.]]--
	function DebugPrint(msg)
		if (not StatsDebug) then return end
		Msg("Stats Debug: "..msg.."\n") 
	end
	
	--[[Another debugger for outputting tables easily]]--
	function DebugPrintTable(Data)
		if (not StatsDebug) then return end
		PrintTable(Data)
	end
	
	--[[New readfile thing]]--
	function ReadFile(steamid)
		local Data = util.KeyValuesToTable(file.Read("stats/stats.txt"))
		local PData = Data[string.lower(steamid)]
		DebugPrint("Reading "..PData["name"].."'s data, outputting contents:")
		DebugPrintTable(PData)
		return PData
	end
	
	function ReadAllData(CheckData)
		local Data = util.KeyValuesToTable(file.Read("stats/stats.txt"))
		if CheckData then
			local Problem = 0
			DebugPrint("Reading ALL data, checking integrety.")
			--local Problem = DataIntegretyCheck(Data)
			if Problem then
				DebugPrint("Some Data Missing, fixed.")
			else
				DebugPrint("All Data Correct")
			end
		else
			DebugPrint("Reading ALL data.")
		end
		return Data
	end
	
	--[[function DataIntegretyCheck(Data) --WIP
		local Problem
		for PID, PlStTable in pairs(Data) do
			for l, w in pairs(PlStTable) do
				if () then
				end
			end
		end
	end]]--
	
	--[[New writefile thing]]--
	function SaveData(pl)
		local Data = (util.KeyValuesToTable(file.Read("stats/stats.txt")))
		Data[string.lower(pl:SteamID())] = pl.PlayerStats
		local PlayerData = Data[string.lower(pl:SteamID())]
		local TotalTime = math.floor((CurTime() - pl.TimeJoined) + pl.InitialJoinTime)
		PlayerData["name"] = pl:Nick()
		PlayerData["time"] = TotalTime
		file.Write("stats/stats.txt",util.TableToKeyValues(Data))
		DebugPrint("Saving "..PlayerData["name"].."'s data with:")
		DebugPrintTable(PlayerData)
	end
	
	hook.Add(	"PlayerDisconnected", "Save on disconnect", SaveData, ply)
	
	--[[]Saves all connected player's data for the routine saves.]]--
	function SaveAllData()
		local AllPlayers = player.GetAll()
		for i, v in pairs(AllPlayers) do
		SaveData(v)
		TTimeHolder, TTime = GetBiggest("time")
		TKillsHolder, TKills = GetBiggest("kills")
		TDeathsHolder, TDeaths = GetBiggest("deaths")
		TSuicidesHolder, TSuicides = GetBiggest("suicides")
		TPropsHolder, TProps = GetBiggest("tpropcount")
		end
	end
	
	--[[Adds new player data to the database]]--
	function AddNewData(pl)
		local Data = (util.KeyValuesToTable(file.Read("stats/stats.txt")))
		Data[string.lower(pl:SteamID())] = {}
		local PlayerData = Data[string.lower(pl:SteamID())]
		PlayerData["name"] = pl:Nick()
		PlayerData["time"] = 0
		PlayerData["lastjoined"] = os.date()
		PlayerData["kills"] = 0
		PlayerData["deaths"] = 0
		PlayerData["suicides"] = 0
		PlayerData["tpropcount"] = 0
		PlayerData["achievements"] = {}
		PlayerData["achievements"]["cocks"] = 0
		pl.PlayerStats = PlayerData
		file.Write("stats/stats.txt",util.TableToKeyValues(Data))
		DebugPrint("Created stats entry for "..pl.PlayerStats["name"]..".")
	end
	
	--[[Check if the stats directory is made..]]--	
	function CheckStatsDir()
		if not (file.IsDir("stats")) then
			file.CreateDir("stats")
			Msg("Created Stats Directory!\n")
		end
		if not (file.Exists("stats/stats.txt")) then
			file.Write("stats/stats.txt", "\"stats\"{}")
			Msg("Created Stats File!\n")
		end
	end
	
	--[[tell the player that he's spawned in, and send time data]]-- work with getting achievement data to send
	function TellPlayerSpawn(pl)
		local Data = pl.PlayerStats
		umsg.Start("PlayerInitialSpawn",pl)
			umsg.Long(Data["time"])
		umsg.End()
	end
	
	function TellPlayerSpawnTimer(pl)
		timer.Create("tellplayerspawntimer", 1, 1, TellPlayerSpawn, pl)
	end
	hook.Add( "PlayerInitialSpawn", "TellPlayerSpawn", TellPlayerSpawnTimer)
	
	--[[Load player's stats file, if none, make the file.]]--
	function LoadPlayerStats(pl) --TEMPORARILY loads kills and deaths to scoreboard.
	local Data = KeyValuesToTable(file.Read("stats/stats.txt"))
		if (Data[string.lower(pl:SteamID())] == nil) then
			AddNewData(pl)
			local Data = ReadFile(pl:SteamID())
			pl:ChatPrint("Created your statistics file, "..Data["name"]..", type statshelp for help.")
		else
			local Data = ReadFile(pl:SteamID())
			Data["name"] = pl:Nick()
			pl:SetDeaths(Data["deaths"])
			pl:SetFrags(Data["kills"])
			pl.PlayerStats = Data
			if !Data["lastjoined"] then
				pl:ChatPrint("Welcome back, "..Data["name"].."!")
			else
				pl:ChatPrint("Welcome back, "..Data["name"].."! Your last visit was on "..Data["lastjoined"].."")
			end
			pl:ChatPrint("Statistics loaded, type statshelp for help.")
			DebugPrint("Loading "..Data["name"].."'s stats, assigning to scoreboard.")
			pl.PlayerStats["lastjoined"] = os.date()
			pl.TimeJoined = math.floor(CurTime())
			DebugPrint("Recorded player's joined time as: "..pl.TimeJoined..".")
			pl.InitialJoinTime = Data["time"]
			SaveData(pl)
		end
	end
	hook.Add( "PlayerInitialSpawn", "LoadPlayerStats", LoadPlayerStats )
	
	--[[Choose what to store, kills, deaths, or suicides?]]--
	function DeathHook(victim, attacker)
		if (attacker == victim) then StoreSuicides(victim) return end
		if (victim:IsValid() && victim:IsPlayer()) then StoreDeaths(victim) end
		if (attacker:IsValid() && attacker:IsPlayer()) then StoreKills(attacker) end
	end
	hook.Add( "DoPlayerDeath", "DeathHook", DeathHook )
	
	--[[Store player kills (only for pvp)]]--
	function StoreKills(pl)
		local Data = pl.PlayerStats
		DebugPrint("Updating "..Data["name"].."'s kills.")
		local PrevKills = Data["kills"]
		DebugPrint(Data["name"].."'s previous kills: "..PrevKills..".")
		Data["kills"] = PrevKills + 1
		local CurKills = Data["kills"]
		DebugPrint(Data["name"].."'s current kills: "..CurKills..".")
		pl.PlayerStats = Data
		DebugPrint("Done updating "..Data["name"].."'s kills.")
		CheckAcheivement(pl, "kills")
	end
	
	--[[Store player deaths (Suicides don't count towards deaths!)]]--
	function StoreDeaths(pl)
		local Data = pl.PlayerStats
		DebugPrint("Updating "..Data["name"].."'s deaths.")
		local PrevDeaths = Data["deaths"]
		DebugPrint(Data["name"].."'s previous deaths: "..PrevDeaths..".")
		Data["deaths"] = PrevDeaths + 1
		local CurDeaths = Data["deaths"]
		DebugPrint(Data["name"].."'s current deaths: "..CurDeaths..".")
		pl.PlayerStats = Data
		DebugPrint("Done updating "..Data["name"].."'s deaths.")
		CheckAcheivement(pl, "deaths")
	end
	
	--[[Store player suicides]]--
	function StoreSuicides(emo)
		local Data = emo.PlayerStats
		DebugPrint("Updating "..Data["name"].."'s suicides.")
		local PrevSuicides = Data["suicides"]
		DebugPrint(Data["name"].."'s previous suicides: "..PrevSuicides..".")
		Data["suicides"] = PrevSuicides + 1
		local CurSuicides = Data["suicides"]
		DebugPrint(Data["name"].."'s current suicides: "..CurSuicides..".")
		emo.PlayerStats = Data
		DebugPrint("Done updating "..Data["name"].."'s suicides.")
		CheckAcheivement(emo, "suicides")
	end
	
	--[[Store how many props the player has spawned.]]--
	function StorePropAmount(pl)
		local Data = pl.PlayerStats
		DebugPrint("Updating "..Data["name"].."'s total spawned prop count.")
		local PrevProps = Data["tpropcount"]
		DebugPrint(Data["name"].."'s previous prop count: "..PrevProps..".")
		Data["tpropcount"] = PrevProps + 1
		local CurProps = Data["tpropcount"]
		DebugPrint(Data["name"].."'s current prop count: "..CurProps..".")
		pl.PlayerStats = Data
		DebugPrint("Done updating "..Data["name"].."'s total spawned prop count.")
		CheckAcheivement(pl, "propsspawned")
	end
	hook.Add( "PlayerSpawnProp", "storepropamount", StorePropAmount )  
	
	--[[Check for acheivememnts! =D]]--
	function CheckAcheivement(pl, achtype)
		if achtype == "suicides" then
			local Data = pl.PlayerStats
			if (Data["suicides"] >= 100) && (Data["achievements"]["cruelworld"]== nil) then
				pl.PlayerStats["achievements"]["cruelworld"] = 1
				TellAllAch(pl, "Goodbye, cruel world")
				SaveData(pl)
			end
		end
		if achtype == "kills" then
			local Data = pl.PlayerStats
			if (Data["kills"] >= 100) && (Data["achievements"]["serialkiller"] == nil) then
				pl.PlayerStats["achievements"]["serialkiller"] = 1
				TellAllAch(pl, "Serial killer")
				SaveData(pl)
			end
		end
		if achtype == "deaths" then
			local Data = pl.PlayerStats
			if (Data["deaths"] >= 100) && (Data["achievements"]["100funerals"] == nil) then
				pl.PlayerStats["achievements"]["100funerals"] = 1
				TellAllAch(pl, "100 \"fun\"erals")
				SaveData(pl)
			end
		end
		if achtype == "propsspawned" then
			local Data = pl.PlayerStats
			if (Data["tpropcount"] >= 100) && (Data["achievements"]["lolpropspam"] == nil) then
				pl.PlayerStats["achievements"]["lolpropspam"] = 1
				TellAllAch(pl, "LOLPROPSPAM")
				SaveData(pl)
			end
		end
	end
	
	--[[Tell all connected players who got what acheivement]]--
	function TellAllAch(pl, strachive)
		local AllPlayers = player.GetAll()
		for i, v in pairs(AllPlayers) do
			v:ChatPrint(pl:Nick().." has earned the achievement: "..strachive.."!")
			v:SendLua([[surface.PlaySound("achievement_earned.mp3")]])
		end
	end
	
	--[[check for chat commands]]--
	function StatsChatHook(pl, text)
		if (string.lower(text) == "mystats") then
			local Data = pl.PlayerStats
			pl:ChatPrint(Data["name"]..", your current statistics are as follows:")
			pl:ChatPrint("Kills: "..Data["kills"])
			pl:ChatPrint("Deaths: "..Data["deaths"])
			pl:ChatPrint("Suicides: "..Data["suicides"])
			pl:ChatPrint("Props spawned: "..Data["tpropcount"])
		elseif (string.lower(text) == "statshelp") then
			pl:ChatPrint("This server is using a custom stats script specially made for Ebnet")
			pl:ChatPrint("It stores a handful of statistics for your viewing pleasure")
			pl:ChatPrint("Commands are as follows:")
			pl:ChatPrint("StatsHelp: This menu.")
			pl:ChatPrint("MyStats: Displays your statistics.")
			pl:ChatPrint("HighScores: Shows the top ranked players for each stat.")
			pl:ChatPrint("[CONSOLE] stats_time_display: 1, awlays active. 2, show for every minute.")
			pl:ChatPrint("If you have any suggestions for features please tell Eb.")
		elseif (string.lower(text) == "highscores") then
			local TDays = tostring(math.floor(TTime / (60 * 60 * 24)))
			local THours = tostring(math.floor(TTime / (60 * 60)) - (TDays * 24))
			local TMinutes = tostring(math.floor(TTime / 60 - (TDays * (24 * 60)) - (THours * 60)))
			local TSeconds = tostring(math.floor(TTime - (TDays * (24 * 60 * 60)) - (THours * 60 * 60) - (TMinutes * 60)))
			pl:ChatPrint("Note: Scores are updated every "..(statssaveinterval / 60).." minutes.")
			pl:ChatPrint("Time:     "..TTimeHolder..": "..(TDays).."D, "..THours..":"..TMinutes..":"..TSeconds..".")
			pl:ChatPrint("Kills:    "..TKillsHolder..": "..TKills..".")
			pl:ChatPrint("Deaths:   "..TDeathsHolder..": "..TDeaths..".")
			pl:ChatPrint("Suicides: "..TSuicidesHolder..": "..TSuicides..".")
			pl:ChatPrint("Props:    "..TPropsHolder..": "..TProps..".")
		end
	end
	hook.Add( "PlayerSay", "StatsChatHook", StatsChatHook )
	
	
	function GetBiggest(stat)
		local Data = ReadAllData()
		local Scoreholder = "None"
		local BiggestValue = 0
		for PID, PlStTable in pairs(Data) do
			for l, w in pairs(PlStTable) do
				if  (Data[PID][stat] > BiggestValue) then
					BiggestValue = Data[PID][stat]
					Scoreholder = Data[PID]["name"]
				end
			end
		end
		return Scoreholder, BiggestValue
	end
	
end
